<template>
  <div ref="playerRef" @fullscreenchange="fullscreenChange" class="player" @mousemove="onMousemove"
       @mouseleave="hideControlbar">
    <div v-if="isPlayError" class="warning-tips">
      <p class="text">您观看的直播已结束哦~</p>
      <img src=".././../assets/image/no-video.png">
      <p class="sub"> 暂无画面</p>
    </div>
    <video ref="playerVideoRef" :autoplay="options.autoplay" @enterpictureinpicture="isPictureInPicture = true"
           @leavepictureinpicture="isPictureInPicture = false" :muted="options.muted"
           class="player-video">

    </video>
    <template v-if="!isPlayError">
      <barrage
          :type="danmuMode"
          :arr="arr"
          :speed="15 - speed"
          :fontSize="fontSize"
          :opacity="opacity"
          :isShow="isShowDanmu"
          :isPause="isPause"
          :percent="100">
      </barrage>
    </template>
    <div class="controlbar" @mousemove="onMousemoveWithControlbar" @mouseleave="isHoverWithControlbar = false"
         :class="{hide: isHideControlbar}">
      <div class="left">
        <div class="play" @click="startPlay" :class="{hide: isPlaying}"></div>
        <div class="pause" @click="pauseVideo" :class="{hide: !isPlaying}"></div>
      </div>
      <div class="right">
        <div class="volume" @click="toggleVolume" :class="{'is-muted': isMuted}"></div>
        <div>
          <el-slider v-model="options.volume" :max="1" :min="0" :step="0.01" :format-tooltip="formatTooltip"
                     class="slider-volume"></el-slider>
        </div>
        <div class="danmu" @click="toggleDanmu" :class="{'show-danmu': isShowDanmu}">
          <div v-if="isShowDanmu" class="setting-panel" @click.stop>
            <div class="row">
              字号大小
              <el-slider v-model="fontSize" :max="32" :min="14" :step="1" :show-tooltip="false"></el-slider>
              {{ format2PercentSign((fontSize - 14) / 18) }}
            </div>
            <div class="row">
              弹幕速度
              <el-slider v-model="speed" height="3" :max="15" :min="0" :step="1" :show-tooltip="false"></el-slider>
              {{ format2PercentSign(speed / 15) }}
            </div>
            <div class="row">
              不透明度
              <el-slider v-model="opacity" :max="1" :min="0" :step="0.1" :show-tooltip="false"></el-slider>
              {{ format2PercentSign(opacity) }}
            </div>
            <div class="select-box">
              <p class="select-box-title">弹幕位置</p>
              <div class="danmu-modes">
                <template v-for="modeItem in danmuModes">
                  <div class="danmu-modes-item" @click="selectDanmuMode(modeItem)" :key="modeItem.type">
                    <img class="icon" :src="danmuMode === modeItem.type ? modeItem.selected : modeItem.unselected">
                    <p class="title">{{ modeItem.title }}</p>
                  </div>
                </template>
              </div>
            </div>
          </div>
        </div>
        <el-tooltip effect="dark" :content="`${isPictureInPicture ? '关闭' : '开启'}画中画`" placement="top">
          <div class="picture-in-picture" @click="togglePictureInPicture" :class="{'is-pip': isPictureInPicture}"></div>
        </el-tooltip>
        <el-tooltip effect="dark" :content="`${isPageFullscreen ? '退出' : ''}网页全屏`" placement="top">
          <div class="page-fullscreen" @click="togglePageFullscreen"
               :class="{'is-pagefullscreen': isPageFullscreen}"></div>
        </el-tooltip>
        <el-tooltip effect="dark" :content="`${isFullscreen ? '退出' : ''}全屏模式`" placement="top">
          <div class="fullscreen" @click="toggleFullscreen" :class="{'is-fullscreen': isFullscreen}"></div>
        </el-tooltip>
      </div>
    </div>
  </div>
</template>

<script>
import flvjs from 'flv.js'
import barrage from './barrage.vue'
import { debounce } from '../../utils'
// 用户交互事件名称
const userInteractEvents = ['touchend', 'click', 'doubleclick', 'keydown']

export default {
  name: 'customPlayer',
  components: { barrage },
  props: {
    options: {
      type: Object,
      default: () => ({
        muted: false,
        autoplay: true,
        volume: 0.5
      })
    },
    cdnPlayUrl: {
      type: Object,
      required: true
    }
  },
  data() {
    // 弹幕模式
    const danmuModes = [
      {
        title: '全屏',
        type: 'fullscreen',
        selected: require('@/assets/danmu_fullscreen_select.png'),
        unselected: require('@/assets/danmu_fullscreen.png')
      }, {
        title: '1/4屏',
        type: 'quarterscreen',
        selected: require('@/assets/danmu_quarterscreen_select.png'),
        unselected: require('@/assets/danmu_quarterscreen.png')
      }, {
        title: '上半屏',
        type: 'uphalf',
        selected: require('@/assets/danmu_uphalf_select.png'),
        unselected: require('@/assets/danmu_uphalf.png')
      }, {
        title: '下半屏',
        type: 'downhalf',
        selected: require('@/assets/danmu_downhalf_select.png'),
        unselected: require('@/assets/danmu_downhalf.png')
      },
    ]
    return {
      danmuModes,
      danmuMode: danmuModes[0].type, // 弹幕模式
      arr: [],
      speed: 5, // 弹幕滚动的速度
      fontSize: 25, // 弹幕字体大小
      opacity: 1, // 弹幕透明度
      isPause: false, // 是否暂停弹幕
      sendContent: null,
      isJs: false,
      isPlayError: false, // 是否播放失败
      direction: 'default',
      isShowDanmu: true, // 是否显示弹幕
      isHoverWithControlbar: false, // 当前鼠标是否在控制条上
      flvPlayer: null, // 播放器对象
      isHideControlbar: true, // 是否隐藏视频底部控制条
      isPlaying: false, // 是否正在播放
      isMuted: false, // 当前是否静音
      isFullscreen: false, // 是否全屏
      isPageFullscreen: false, // 是否网页全屏
      isPictureInPicture: false, // 是否开启画中画
      oldVolume: this.options.volume, // 静音/有音切换时
    }
  },
  mounted() {
    this.$bus.$on('sendTextMessage', (message) => {
      console.log('message', message)
      this.sendContent = message
      this.sendBarrage()
    })
    this.containerPc = document.querySelector('.container-pc')
    this.containerPc.onfullscreenchange = () => {
      this.isPageFullscreen = !!document.fullscreenElement
    }
    const url1 = this.cdnPlayUrl.flv
    const url2 = 'https://3891.liveplay.myqcloud.com/live/1400188366_707802266_127229_main.flv'
    this.flvPlayer = flvjs.createPlayer({
      type: 'flv',
      isLive: true,
      url: process.env.NODE_ENV === 'production' ? url1 : url2,
      // url: url1,
    })
    this.flvPlayer.attachMediaElement(this.$refs['playerVideoRef'])
    this.flvPlayer.on('error', (e) => {
      console.log('播放失败', e)
      this.isPlayError = true
    })
    this.flvPlayer.load()
    this.startPlay()
    this.initTestData()
    userInteractEvents.forEach(eventName => document.body.addEventListener(eventName, this.startPlay))
    this.$once('hook:beforeDestroy', this.clearUserInteractEvents)
  },
  watch: {
    'options.volume'(val, oldVal) {
      this.flvPlayer.volume = val
      this.isMuted = !val
      this.oldVolume = oldVal
    }
  },
  methods: {
    selectDanmuMode({ type }) { // 选择弹幕的模式
      this.danmuMode = type
    },
    format2PercentSign(val) {
      return `${~~(val * 100)}%`
    },
    fullscreenChange() {
      this.isFullscreen = !!document.fullscreenElement
    },
    togglePictureInPicture() {
      if (document.pictureInPictureElement) {
        document.exitPictureInPicture()
      } else {
        if (document.pictureInPictureEnabled) {
          console.log('this.flvPlayer', this.flvPlayer)
          this.$refs.playerVideoRef.requestPictureInPicture()
        }
      }
      this.isPictureInPicture = !document.pictureInPictureElement
    },
    togglePageFullscreen() { // 切换网页全屏
      if (!document.fullscreenElement) {
        this.containerPc.requestFullscreen()
      } else {
        if (document.exitFullscreen) {
          document.exitFullscreen()
        }
      }
      this.isFullscreen = !document.fullscreenElement
    },
    toggleFullscreen() { // 切换全屏播放状态
      // this.isFullscreen = !this.isFullscreen
      if (!document.fullscreenElement) {
        this.$refs.playerRef.requestFullscreen()
      } else {
        if (document.exitFullscreen) {
          document.exitFullscreen()
        }
      }
      this.isFullscreen = !document.fullscreenElement
    },
    toggleDanmu() { // 切换弹幕显隐状态
      this.isShowDanmu = !this.isShowDanmu
    },
    // 初始化模拟弹幕数据
    initTestData() {
      let arr = [
        '不是，真不是，你听我狡辩',
        '主播，翻我翻我',
        '爷请回！爷请回！',
        '这腿质量真好，啊不，这车真白',
        '这歌真白...不是...这腿真好听...啊呸...我真是来看歌的(ಡωಡ)',
        '我只会心疼giegie',
        '我不是，我没有，别乱说',
        '这里的弹幕的水很深，你把握不住，让叔来！'
      ]
      for (let i = 0; i < 6; i++) {
        for (let index = 0; index < 1000; index++) {
          // if (index % 2 == 0) {
          //   this.arr.push({
          //     direction: 'top',
          //     content: arr[parseInt(Math.random() * arr.length)]
          //   })
          // } else {
          this.arr.push({
            direction: 'default',
            content: arr[parseInt(Math.random() * arr.length)]
          })
          // }
        }
      }
    },
    // 发送弹幕
    sendBarrage() {
      if (this.arr.length > 1 && this.sendContent != '' && this.sendContent != null) {
        this.arr.unshift({
          content: this.sendContent,
          direction: this.direction,
          isSelf: true,
          style: {
            color: 'red',
            fontSize: '25px'
          },
          isJs: this.isJs
        })
      } else {
        this.arr.push({
          content: this.sendContent,
          direction: this.direction,
          isSelf: true,
          style: {
            color: 'red'
          },
          isJs: this.isJs
        })
      }
      this.sendContent = null
    },
    formatTooltip(val) {
      return `音量${~~(val * 100)}%`
    },
    clearUserInteractEvents() {
      userInteractEvents.forEach(eventName => document.body.removeEventListener(eventName, this.startPlay))
    },
    toggleVolume() {
      this.isMuted = !this.isMuted
      this.options.volume = this.isMuted ? 0 : this.oldVolume
    },
    onMousemoveWithControlbar() {
      this.isHideControlbar = false
      this.isHoverWithControlbar = true
    },
    onMousemove() { // 鼠标在视频上移动事件
      this.isHideControlbar = false
      this.hideWithNoOperation()
    },
    hideControlbar() { // 隐藏控制栏
      if (!this.isHoverWithControlbar) {
        this.isHideControlbar = true
      }
    },
    hideWithNoOperation: debounce(function () { // 用户无操作时隐藏控制栏
      this.hideControlbar()
    }, 1500),
    startPlay() { // 开始播放
      const promise = this.flvPlayer.play()
      if (!Object.is(promise, undefined)) {
        promise.then(_ => {
          console.log('当前页面支持自动播放')
          this.isPause = false
          this.isPlaying = true
          this.flvPlayer.volume = this.options.volume
          this.clearUserInteractEvents()
        }).catch(err => {
          console.log('当前页面不支持自动播放', err)
          this.isPlaying = false
        })
      }
    },
    pauseVideo() { // 暂停播放
      this.isPlaying = false
      this.flvPlayer.pause()
      // this.isPause = true
    },
  }
}
</script>

<style lang="stylus" scoped>
setIcon(path) {
  width 24px
  height 24px
  cursor pointer
  background-image url(path)
  background-repeat no-repeat
  background-size contain
}

setSettingPanel(name) {
  {name} {
    display none
    font-size 14px
    color white
    border-radius 5px
  }
  &:hover {name} {
    display block
    position absolute
    left 50%
    bottom 40px
    padding 12px 20px
    transform translateX(-50%)
    background-color rgba(0, 0, 0, .6)
    cursor text

    &::after {
      content ''
      position absolute
      bottom -20px
      left 0
      height 20px
      width 100%
      background-color transparent
    }
  }
}

.player {
  position relative
  height 100%
  overflow hidden

  ::v-deep .el-slider__runway {
    height 4px

    .el-slider__bar {
      height 4px
    }

    .el-slider__button-wrapper {
      width 8px
      height 8px
      top -9px

      .el-slider__button {
        width 8px
        height 8px
      }
    }
  }


  .warning-tips {
    position absolute
    left 50%
    top 50%
    transform translate(-50%, -50%)
    color white
    display flex
    flex-direction column
    justify-content center

    .text {
      margin-bottom 20px
    }

    .sub {
      font-size: 24px;
      color: #8A9099;
      text-align: center;
      margin-top: 30px;
    }
  }

  .player-video {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .controlbar {
    position absolute
    bottom 0
    width 100%
    height 42px
    transition transform .2s ease-out, opacity .2s ease-out
    background linear-gradient(0deg, rgba(0, 0, 0, .8), rgba(0, 0, 0, 0.75, 48%), transparent)
    user-select none
    display flex
    justify-content space-between
    z-index 10

    &.hide {
      transform translateY(42px)
    }

    .left {
      display flex

      > div {
        margin-left 20px
      }

      .play, .pause {
        setIcon("~@/assets/play.png")

        &.hide {
          display none
        }
      }

      .pause {
        background-image url("~@/assets/pause.png")
      }
    }

    .right {
      display flex
      align-items center

      > div {
        margin-right 20px
      }

      ::v-deep .slider-volume.el-slider {
        width 100px

        .el-slider__button-wrapper {
          top -11px
        }
      }

      .volume {
        setIcon("~@/assets/volume.webp")

        &.is-muted {
          background-image url("~@/assets/volume_mute.webp")
        }
      }

      .danmu {
        position relative
        setIcon("~@/assets/hidedanmu.webp")

        &.show-danmu {
          background-image url("~@/assets/showdanmu.webp")
        }
        setSettingPanel('.setting-panel')

        .setting-panel {
          width 260px

          > div {
            margin-bottom 15px
          }

          .row {
            display flex
            align-items center
            white-space nowrap

            ::v-deep .el-slider {
              width 140px
              margin 0 12px
            }
          }

          .select-box {
            &-title {
              margin-bottom 14px
            }

            .danmu-modes {
              display flex
              justify-content space-between

              &-item {
                display flex
                flex-direction column
                align-items center
                cursor pointer

                .icon {
                  width 40px
                }

                .title {
                  margin-top 12px
                  font-size 12px
                }
              }
            }
          }
        }
      }

      .fullscreen {
        setIcon("~@/assets/fullscreen.webp")

        &.is-fullscreen {
          background-image url("~@/assets/fullscreen_exit.webp")
        }
      }

      .picture-in-picture {
        setIcon("~@/assets/picinpic.svg")
        transform scale(1.66)

        &.is-pip {
          background-image url("~@/assets/picinpic_exit.svg")
        }
      }

      .page-fullscreen {
        setIcon("~@/assets/pagescreen.webp")

        &.is-pagefullscreen {
          background-image url("~@/assets/pagescreen_exit.webp")
        }
      }
    }
  }
}
</style>
